package cn.qingyun.gis.modules.express.util;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;

@Slf4j
public class SyncTool {
    private SyncTool() {
        throw new IllegalStateException("Utility class");
    }

    @SneakyThrows
    public static void doSync(int countDown, IntConsumer consumer) {
        doSync(countDown, 30 * 60, consumer);
    }

    @SneakyThrows
    public static void doSync(int countDown, int awaitSeconds, IntConsumer consumer) {
        doSync(countDown, awaitSeconds, consumer, null);
    }


    @SneakyThrows
    public static void doSync(int countDown, int awaitSeconds, IntConsumer consumer, Integer queueCapacity) {
        final ThreadPoolTaskExecutor executor;
        if (ObjectUtil.isNull(queueCapacity)) {
            executor = ThreadPoolTool.singletonExecutor();
        } else {
            executor = ThreadPoolTool.callerRunsPolicyExecutor(queueCapacity);
        }

        ThreadPoolTool.startPrintThreadPoolInfo(executor);
        CountDownLatch countDownLatch = new CountDownLatch(countDown);
        for (int i = 1; i < countDown + 1; i++) {
            int finalI = i;
            executor.submit(() -> {
                try {
                    consumer.accept(finalI);
                } catch (Exception e) {
                    log.error("线程执行错误", e);
                } finally {
                    DynamicDataSourceContextHolder.clear();
                    countDownLatch.countDown();
                    log.debug("SyncTool -----------------------------------------------------------------  countDownLatch {}", countDownLatch.getCount());
                }
            });
        }
        log.debug("SyncTool 等待线程结束 {}", countDown);
        boolean awaited = countDownLatch.await(awaitSeconds, TimeUnit.SECONDS);
        if (!awaited) {
            executor.shutdown();
        }
        ThreadPoolTool.endPrintThreadPoolInfo();
        log.debug("SyncTool 线程执行结束 {} {}", countDown, awaited);
    }

}
